﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

using System.Drawing.Drawing2D;
using System.ComponentModel;

namespace AnaViewer
{
    public enum SwitchMode
    {
        /// <summary>
        /// 立即更新
        /// </summary>
        Immediately,
        /// <summary>
        /// 渐隐渐显
        /// </summary>
        FadeInFadeOut,
    }

    /// <summary>
    /// 提供对一个项的显示。
    /// </summary>
    partial class AnaForm : AlphaForm//: Form
    {
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
                return cp;
            }
        }


        Properties.Settings settings = Properties.Settings.Default;

        AnaPainter anaPainter;

        /// <summary>
        /// 文章更换计时器。
        /// </summary>
        private Timer articleTimer;

        /// <summary>
        /// 负责界面的刷新
        /// </summary>
        private Timer uiTimer;
        public AnaForm()
        {
            InitializeComponent();
            this.ImeMode = ImeMode.Close;

            InitializeMenus();
            SetControlDragEnable(this);

            anaPainter = new AnaPainter(this, new Rectangle(0, 0, this.Width, this.Height));

            //InitializeMenus();

            articleTimer = new Timer();
            articleTimer.Interval = 1000 * 10;
            articleTimer.Tick += delegate(object sender, EventArgs e) { subject.NextArticle(); };


            uiTimer = new Timer();
            uiTimer.Interval = 20;
            uiTimer.Tick += delegate(object sender, EventArgs e) { RefreshUI(); };

            anaPainter.AnaDoubleClick += delegate(object sender, EventArgs e) { Program.ShowMainForm(); };
            anaPainter.ToolButtonClick += new EventHandler<AnaPainter.ToolButtonEventArgs>(anaPainter_ToolButtonClick);
            anaPainter.AuthorFaceClick += new EventHandler(anaPainter_AuthorFaceClick);
            anaPainter.ToolBarLogoClick += new EventHandler(anaPainter_ToolBarLogoClick);




            this.OprModeChanged += delegate(object sender, EventArgs e)
            {
                articleTimer.Enabled = !this.OprMode;
            };

            InitializeMenuThemes(this.menuThemes);

            settings.SettingsSaving += delegate(object sender, CancelEventArgs e)
            {
                ThemeData data = themeHelper.GetThemeData(settings.AnaTheme);
                anaPainter.UpdateTheme(data);

                LoadAnaFormSettings();
            };
        }
        /// <summary>
        /// 语录的最大大小
        /// </summary>
        public Size AnaSize
        {
            get { return anaPainter.Bounds.Size; }
            set { anaPainter.Bounds = new Rectangle(new Point(0, 0), value); }
        }

#if DEBUG
        int freshCount = 0;
#endif
        /// <summary>
        /// 正在刷新中
        /// </summary>
        bool refreshing = false;
        /// <summary>
        /// 刷新界面
        /// </summary>
        public void RefreshUI()
        {
            if (refreshing)//不需要刷新 或 正在刷新
                return;
            refreshing = true;

            if (anaPainter.IsInvalid)
            {
                anaPainter.RefreshUI();
#if DEBUG
                Debug.Print("刷新次数: {0}", freshCount++);
#endif
                if (anaPainter.ScreenBitmap != null)
                    this.SetBitmap(anaPainter.ScreenBitmap, (byte)alpha);
            }
            refreshing = false;
        }


        SwitchMode switchMode = SwitchMode.FadeInFadeOut;
        public SwitchMode SwitchMode
        {
            get { return switchMode; }
            set { switchMode = value; }
        }

        AnaSubject subject;
        public AnaSubject Subject
        {
            get { return subject; }
            set
            {
                subject = value;
                if (subject != null)
                {
                    subject.SelectedIndexChanged += new EventHandler(subject_SelectedIndexChanged);
                }
            }
        }

        IItem displayItem;
        public IItem DisplayItem
        {
            get { return displayItem; }
        }
        void subject_SelectedIndexChanged(object sender, EventArgs e)
        {
            IItem value = subject.SelectedItem;
            switch (switchMode)
            {
                case SwitchMode.Immediately:// 立即更换显示项。
                    displayItem = value;
                    anaPainter.DisplayItem = displayItem;
                    break;
                case SwitchMode.FadeInFadeOut:// 渐隐渐显地显示项。
                    displayItem = value;

                    if (anaPainter.DisplayItem == null)
                    {//仅仅渐出
                        anaPainter.DisplayItem = displayItem;//显示当前文章
                        ShowArticle_Flash();
                    }
                    else
                    {//渐隐渐出
                        StartChangeArticle();
                    }
                    break;
            }
        }


        #region 渐隐渐显效果

        byte alpha = 255;
        public byte Alpha
        {
            get
            {
                return alpha;
            }
            set
            {
                alpha = value;
                if (anaPainter.ScreenBitmap != null)
                    this.SetBitmap(anaPainter.ScreenBitmap, alpha);
            }
        }




        // 初始的 alpha 值及该值每次的更改量
        private int textAlpha = 0;
        private int textAlphaDelta = 4;
        private int textAlphaMax = 255;
        /// <summary>
        /// 渐变计时器。
        /// </summary>
        private Timer fadeTimer;

        private void fadeTimer_Tick(object sender, EventArgs e)
        {
            // 更改要绘制的文本的 alpha 值
            // 逐步增加值，直至达到 textAlphaMax，然后再逐步减小值
            // 当值重新为零时移动到下一文章
            textAlpha += textAlphaDelta;
            if (textAlpha >= textAlphaMax)
            {
                fadeTimer.Stop();
                textAlpha = textAlphaMax;
            }
            else if (textAlpha <= 0)
            {//完全不见时，更改文章
                fadeTimer.Stop();
                textAlpha = 0;


                anaPainter.DisplayItem = displayItem;//显示当前文章
                ShowArticle_Flash();

                GC.Collect();
            }

            this.Alpha = (byte)textAlpha;
        }
        /// <summary>
        /// 渐出效果显示。
        /// </summary>
        public void ShowArticle_Flash()
        {
            this.Alpha = 0;

            //切换后，渐渐地显示该项。
            if (fadeTimer == null)
            {
                fadeTimer = new Timer();
                fadeTimer.Tick += new EventHandler(fadeTimer_Tick);
                fadeTimer.Interval = 40;
            }
            //从不见到可见
            textAlpha = 0;
            textAlphaDelta = 4;
            fadeTimer.Start();
        }


        /// <summary>
        /// 更换文章，渐入渐出效果
        /// </summary>
        public void StartChangeArticle()
        {
            if (fadeTimer == null)
            {
                fadeTimer = new Timer();
                fadeTimer.Tick += new EventHandler(fadeTimer_Tick);
                fadeTimer.Interval = 40;
            }
            //从可见到不可见
            textAlpha = textAlphaMax;
            textAlphaDelta = -4;

            this.Alpha = (byte)textAlpha;
            fadeTimer.Start();
        }
        #endregion

        protected override void OnContextMenuChanged(EventArgs e)
        {
            if (this.ContextMenuStrip != null)
            { }
            base.OnContextMenuChanged(e);
        }

        void anaPainter_ToolBarLogoClick(object sender, EventArgs e)
        {//Logo
            //this.ContextMenuStrip.Show(this, e.Location);
        }

        void anaPainter_AuthorFaceClick(object sender, EventArgs e)
        {
            //当前项，即 anaPainter 当前显示的项。
            IItem curItem = anaPainter.DisplayItem;
            if (curItem != null)
            {
                if (curItem.GetType() == typeof(AnaItem))
                {
                    Person person = (curItem as AnaItem).Person;
                    if (person != null && person.Name != null && person.Name.Trim() != "")
                        Yandui.GoUrl_RenwuSerch(person.Name);

                    //Common.GoUrl_RenwuView(item.Person.Id);
                }
                else if (curItem.GetType() == typeof(RssItem))
                {//直接访问网站
                    string url = subject.DataSet.Link;
                    if (url != null && url.Trim() != "")
                        Common.GoUrl(url);
                }
            }
        }

        void anaPainter_ToolButtonClick(object sender, AnaPainter.ToolButtonEventArgs e)
        {
            //当前项，即 anaPainter 当前显示的项。
            IItem curItem =anaPainter.DisplayItem;
            switch (e.Button.Text)//toolBar.GetItemIndex(btn)
            {
                case "查看"://查看，RSS 或 ANA
                    if (curItem != null)
                    {
                        string url = curItem.Link;
                        if(url != null && url.Trim() != "")
                            Common.GoUrl(url);

                        //if (curItem.GetType() == typeof(AnaItem))
                        //{
                        //    string anaId = (curItem as AnaItem).AnaId;
                        //    if (anaId != null && anaId.Trim() != "")
                        //        Yandui.GoUrl_YuluView(anaId);
                        //}
                    }
                    break;
                case "编辑"://编辑，仅支持 ANA
                    if (curItem != null)
                    {
                        if (curItem.GetType() == typeof(AnaItem))
                        {
                            string anaId = (curItem as AnaItem).AnaId;
                            if (anaId != null && anaId.Trim() != "")
                                Yandui.GoUrl_YuluEdit(anaId);
                        }
                    }
                    break;
                case "评论"://评论
                    if (curItem != null)
                    {
                        if (curItem.GetType() == typeof(AnaItem))
                        {
                            string anaId = (curItem as AnaItem).AnaId;
                            if (anaId != null && anaId.Trim() != "")
                                Yandui.GoUrl_YuluComment(anaId);
                        }
                        else if (curItem.GetType() == typeof(RssItem))
                        {
                            string url = (curItem as RssItem).Comments;
                            if (url != null && url.Trim() != "")
                                Common.GoUrl(url);
                        }
                        else
                        { }
                    }
                    break;
                case "收藏"://收藏
                    break;
                case "喜欢"://喜欢
                    break;
                case "不喜欢"://不喜欢
                    break;
                case "举报"://举报
                    break;
                case "头像":
                    anaPainter.AuthorVisible = !anaPainter.AuthorVisible;
                    break;
                case "上篇":
                    if (subject != null)
                        subject.PreviousArticle();
                    break;
                case "随机":
                    if (subject != null)
                        subject.ChangeArticle();
                    break;
                case "下篇":
                    if (subject != null)
                        subject.NextArticle();
                    break;
                default:
                    break;
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {//在隐藏时不需要刷新界面
            if (this.Visible)
            {
                RefreshUI();
                uiTimer.Start();
            }
            else
            {
                uiTimer.Stop();
            }
            base.OnVisibleChanged(e);
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (isQuit)
            {//程序自己要退出
            }
            else
            {//其他原因
                switch (e.CloseReason)
                {
                    case CloseReason.WindowsShutDown://操作系统要求，则直接退出
                        break;
                    default:
                        e.Cancel = true;
                        break;
                }
            }

            if (!e.Cancel)
            {//真的要退出了
                uiTimer.Stop();
                articleTimer.Stop();
                notifyIcon.Visible = false;

                SaveAnaFormSettings();
            }

            base.OnFormClosing(e);
        }
        bool isQuit = false;
        public void CloseMe()
        {
            isQuit = true;
            this.Close();
            isQuit = false;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            //因为只有在AnaForm显示后对其位置等属性设置才起作用
            LoadAnaFormSettings();
            articleTimer.Start();
        }

        ThemeHelper themeHelper = ThemeHelper.Default;
        /// <summary>
        /// 初始化风格菜单
        /// </summary>
        /// <param name="menuThemes"></param>
        public void InitializeMenuThemes(ToolStripMenuItem menuThemes)
        {
            menuThemes.DropDownItems.Clear();

            ToolStripMenuItem menu;
            foreach (string themeText in ThemeHelper.Default.SupportThemeNames)
            {
                menu = new ToolStripMenuItem(themeText);
                menuThemes.DropDownItems.Add(menu);
                menu.Click += delegate(object sender, EventArgs e)
                {
                    settings.AnaTheme = (sender as ToolStripMenuItem).Text;
                    anaPainter.UpdateTheme(themeHelper.GetThemeData(settings.AnaTheme));
                };
            }
            menuThemes.DropDownItems.Add(new ToolStripSeparator());

            menu = new ToolStripMenuItem("主题管理器(&M)...");
            menuThemes.DropDownItems.Add(menu);
            menu.Click+= delegate(object sender, EventArgs e)
            {//编辑风格
                ThemeManagerForm form = new ThemeManagerForm();
                form.ShowDialog(this.TopLevelControl);
                //刷新主题列表菜单
                InitializeMenuThemes(menuThemes);
            };

            menuThemes.DropDownOpening += delegate(object sender, EventArgs e)
            {
                foreach (ToolStripItem item in menuThemes.DropDownItems)
                {
                    ToolStripMenuItem theMenu =item as ToolStripMenuItem;
                    if (theMenu == null)
                        return;
                    else
                        theMenu.Checked = (item.Text == settings.AnaTheme);
                }
            };
        }

        /// <summary>
        /// 载入 AnaForm 设置。
        /// </summary>
        void LoadAnaFormSettings()
        {
            subject.FreshDataInterval = settings.FreshDataInterval;// 60
            articleTimer.Interval = settings.ChangeArticleInterval * 1000;//10 * 1000 // 更换文章的时间间隔。
            subject.FreshDataEnabled = settings.AutoFreshData;
            articleTimer.Enabled = settings.AutoChangeArticle;


            anaPainter.UpdateTheme(themeHelper.GetThemeData(settings.AnaTheme));


            // ----------- 窗口样式 | FormStyle -----------
            Size size = settings.AnaSize;
            if (size.Width > 1024) size.Width = 1024;
            if (size.Width < 128) size.Width = 128;
            if (size.Height > 768) size.Height = 768;
            if (size.Height < 64) size.Height = 64;
            this.AnaSize = size;
            this.Location = settings.AnaLocation;
            InsureFormVisible();

            if (this.CanPenetrate != settings.AnaMouseLocked)
                this.CanPenetrate = settings.AnaMouseLocked;//false
            if (this.EmbedDesktop != settings.AnaEmbedDesktop)
                this.EmbedDesktop = settings.AnaEmbedDesktop;//true
            this.FormLocked = settings.AnaLocationLocked;//true
            this.OpacityPercent = settings.AnaOpacityPercent;//100

            if (this.EmbedDesktop)
                Common.ToggleDesktop();
            this.Activate();
        }

        /// <summary>
        /// 保存 AnaForm 设置。
        /// </summary>
        void SaveAnaFormSettings()
        {
            settings.AnaLocation = this.Location;
            //settings.AnaForm_Size = anaForm.Size;
            settings.AnaMouseLocked = this.CanPenetrate;
            settings.AnaEmbedDesktop = this.EmbedDesktop;
            settings.AnaLocationLocked = this.FormLocked;
            settings.AnaOpacityPercent = this.OpacityPercent;

            settings.Save();
        }





        /// <summary>
        /// 对窗体操作模式（显示半透明背景和工具栏）
        /// </summary>
        bool oprMode = false;
        public bool OprMode
        {
            get { return oprMode; }
            set
            {
                if (oprMode == value)
                    return;

                oprMode = value;
                if (oprMode)
                {
                    //textAlpha = textAlphaMax;
                    alpha = 255;

                    if (fadeTimer != null)
                        fadeTimer.Stop();
                }
                else
                {
                    //fadeTimer.Start();
                }
                OnOprModeChanged(new EventArgs());


                this.SwitchMode = this.OprMode ? SwitchMode.Immediately : SwitchMode.FadeInFadeOut;

                anaPainter.OprMode = oprMode;
            }
        }

        public event EventHandler OprModeChanged;
        protected virtual void OnOprModeChanged(EventArgs e)
        {
            if (OprModeChanged != null)
                OprModeChanged(this, e);
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            anaPainter.IsHover = true;
            base.OnMouseEnter(e);
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            anaPainter.IsHover = false;
            base.OnMouseLeave(e);
        }
        protected override void OnActivated(EventArgs e)
        {
            this.OprMode = true;
            base.OnActivated(e);
        }
        protected override void OnDeactivate(EventArgs e)
        {
            anaPainter.IsHover = false;//鼠标肯定也离开了
            this.OprMode = false;
            base.OnDeactivate(e);
        }

        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            anaPainter.OnMouseDoubleClick(e);
            base.OnMouseDoubleClick(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            anaPainter.OnMouseMove(e);
            base.OnMouseMove(e);
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            anaPainter.OnMouseDown(e);
            base.OnMouseDown(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            anaPainter.OnMouseUp(e);
            base.OnMouseUp(e);
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            anaPainter.OnMouseClick(e);
            base.OnMouseClick(e);
        }







        #region 窗口拖动
        /// <summary>
        /// 确保窗口完全处于 主屏幕 的区域内。
        /// </summary>
        void InsureFormVisible()
        {
            Rectangle bounds = Screen.PrimaryScreen.Bounds;
            Rectangle setRect = new Rectangle(this.Location, AnaSize);
            //if (!bounds.Contains(setRect))
            {//按照设置值，语录将无法全部显示在主屏幕内
                int mergin = 5;
                if (setRect.Left < bounds.Left + mergin)
                    setRect.X = bounds.Left + mergin;
                if (setRect.Right > bounds.Right - mergin)
                    setRect.X -= setRect.Right - (bounds.Right - mergin);
                if (setRect.Top < bounds.Top + mergin)
                    setRect.Y = (bounds.Top + mergin);
                if (setRect.Top + 150 > bounds.Bottom)
                    setRect.Y -= (setRect.Top + 150) - bounds.Bottom;

                this.Location = setRect.Location;
            }
        }

        Control ctrl;
        /// <summary>
        /// 设置一个控件为可拖动。
        /// </summary>
        /// <param name="ctrl"></param>
        void SetControlDragEnable(Control ctrl)
        {
            this.ctrl = ctrl;
            ctrl.MouseDown += new MouseEventHandler(Ctrl_MouseDown);
            ctrl.MouseMove += new MouseEventHandler(Ctrl_MouseMove);
            ctrl.MouseUp += new MouseEventHandler(Ctrl_MouseUp);
        }





        //// Let Windows drag this form for us
        //protected override void WndProc(ref Message m)
        //{
        //    if (m.Msg == 0x0084 /*WM_NCHITTEST*/)
        //    {
        //        m.Result = (IntPtr)2;	// HTCLIENT
        //        return;
        //    }
        //    base.WndProc(ref m);
        //}

        /// <summary>
        /// Gets or sets 一个值，指示是否 [form locked]。
        /// </summary>
        /// <value>如果 [form locked]为 <c>true</c>；否则为 <c>false</c>。</value>
        public bool FormLocked
        {
            get { return m_FormLocked; }
            set { m_FormLocked = value; }
        }


        /// <summary>
        /// 如果锁定,则不移动
        /// </summary>
        private bool m_FormLocked = false;
        /// <summary>
        /// 记录鼠标指针的坐标
        /// </summary>
        private Point mouseOffset;
        /// <summary>
        /// 记录鼠标按键是否按下。修改鼠标状态 isMouseDown 的值
        /// </summary>
        private bool isMouseDown = false;
        public void Ctrl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {// 确保只有鼠标左键按下并移动时，才移动窗体
                mouseOffset = e.Location;
                ctrl.Cursor = Cursors.Hand;
                isMouseDown = true;
            }
        }
        public void Ctrl_MouseMove(object sender, MouseEventArgs e)
        {
            if (!m_FormLocked && isMouseDown)
            {
                Point pos = ctrl.Location;
                pos.Offset(e.X - mouseOffset.X, e.Y - mouseOffset.Y);
                ctrl.Location = pos;
            }
        }
        public void Ctrl_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = false;
                ctrl.Cursor = Cursors.Default;

                InsureFormVisible();
            }
        }
        #endregion
    }
}
